package com.fumasoft.dynamic.config;

import com.alibaba.ttl.threadpool.TtlExecutors;
import java.util.concurrent.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * 线程池配置.
 */
@Configuration
@Component
public class ThreadPoolConfig {

    /**
     * 核心线程数.
     */
    public static final int CORE_POOL_SIZE = 200;

    /**
     * 最大线程数.
     */
    public static final int MAX_POOL_SIZE = 300;

    /**
     * 队列容量.
     */
    public static final int QUEUE_CAPACITY = 1000;

    /**
     *  常量定义 for Common ThreadPool.
     */
    public static final String THREAD_POOL_NAME_PREFIX = "commonThreadPool-";

    /**
     *  常量定义 for Normal ThreadPool.
     */
    public static final String NORMAL_THREAD_POOL_NAME_PREFIX = "normalThreadPool-";


    /**
     * 支持线程通讯.
     *
     * @return Executor
     */
    @Bean(value = "billCommonThreadPool")
    public Executor billCommonThreadPool() {
        return initThreadPool(CORE_POOL_SIZE, CORE_POOL_SIZE, MAX_POOL_SIZE, QUEUE_CAPACITY, THREAD_POOL_NAME_PREFIX);
    }

    /**
     * 一般线程池.
     *
     * @return Executor
     */
    @Bean(value = "billNormalThreadPool")
    public ThreadPoolTaskExecutor billNormalThreadPool() {
        return initNormalThreadPool(CORE_POOL_SIZE, CORE_POOL_SIZE, MAX_POOL_SIZE, QUEUE_CAPACITY, NORMAL_THREAD_POOL_NAME_PREFIX);
    }

    /**
     * 初始化线程池.
     *
     * @param maxSize 最大线程数
     * @param coreSize 核心线程数
     * @param keepAlive 线程空闲时间
     * @param queueCapacity 队列容量
     * @param threadNamePrefix 线程前缀
     * @return Executor
     */
    private Executor initThreadPool(Integer maxSize,
                                    Integer coreSize,
                                    Integer keepAlive,
                                    Integer queueCapacity,
                                    String threadNamePrefix) {
        ThreadFactory springFactory = new CustomizableThreadFactory(threadNamePrefix);
        ExecutorService exec = new ThreadPoolExecutor(
                coreSize,
                maxSize,
                keepAlive,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(queueCapacity),
                springFactory,
                new ThreadPoolExecutor.CallerRunsPolicy());
        exec = TtlExecutors.getTtlExecutorService(exec);
        return exec;
    }

    /**
     * 初始化线程池.
     *
     * @param maxSize 线程池最大线程数
     * @param coreSize 线程池核心线程数
     * @param keepAlive 线程空闲时间
     * @param queueCapacity 队列容量
     * @param threadNamePrefix 线程前缀
     * @return ThreadPoolTaskExecutor
     */
    private ThreadPoolTaskExecutor initNormalThreadPool(Integer maxSize,
                                                        Integer coreSize,
                                                        Integer keepAlive,
                                                        Integer queueCapacity,
                                                        String threadNamePrefix) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(coreSize);
        executor.setMaxPoolSize(maxSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAlive);
        executor.setThreadNamePrefix(threadNamePrefix);
        // 拒绝策略 使用主线程
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

}
